Completed
Push — master ( 5bf5a9...80b817 )
by Rain
01:36
created

qr.js ➔ generateFrame   F

Complexity

Conditions 71
Paths 0

Size

Total Lines 407

Duplication

Lines 6
Ratio 1.47 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 71
nc 0
dl 6
loc 407
rs 2
c 1
b 0
f 0
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like qr.js ➔ generateFrame often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
// [qr.js](http://neocotic.com/qr.js)  
2
// (c) 2015 Alasdair Mercer  
3
// Licensed under the GPL Version 3 license.  
4
// Based on [jsqrencode](http://code.google.com/p/jsqrencode/)  
5
// (c) 2010 [email protected]  
6
// Licensed under the GPL Version 3 license.  
7
// For all details and documentation:  
8
// <http://neocotic.com/qr.js>
9
10
(function (root) {
11
12
  'use strict';
13
14
  // Private constants
15
  // -----------------
16
17
  // Alignment pattern.
18
  var ALIGNMENT_DELTA = [
19
    0,  11, 15, 19, 23, 27, 31,
20
    16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
21
    26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
22
  ];
23
  // Default MIME type.
24
  var DEFAULT_MIME = 'image/png';
25
  // MIME used to initiate a browser download prompt when `qr.save` is called.
26
  var DOWNLOAD_MIME = 'image/octet-stream';
27
  // There are four elements per version. The first two indicate the number of blocks, then the
28
  // data width, and finally the ECC width.
29
  var ECC_BLOCKS = [
30
    1,  0,  19,  7,     1,  0,  16,  10,    1,  0,  13,  13,    1,  0,  9,   17,
31
    1,  0,  34,  10,    1,  0,  28,  16,    1,  0,  22,  22,    1,  0,  16,  28,
32
    1,  0,  55,  15,    1,  0,  44,  26,    2,  0,  17,  18,    2,  0,  13,  22,
33
    1,  0,  80,  20,    2,  0,  32,  18,    2,  0,  24,  26,    4,  0,  9,   16,
34
    1,  0,  108, 26,    2,  0,  43,  24,    2,  2,  15,  18,    2,  2,  11,  22,
35
    2,  0,  68,  18,    4,  0,  27,  16,    4,  0,  19,  24,    4,  0,  15,  28,
36
    2,  0,  78,  20,    4,  0,  31,  18,    2,  4,  14,  18,    4,  1,  13,  26,
37
    2,  0,  97,  24,    2,  2,  38,  22,    4,  2,  18,  22,    4,  2,  14,  26,
38
    2,  0,  116, 30,    3,  2,  36,  22,    4,  4,  16,  20,    4,  4,  12,  24,
39
    2,  2,  68,  18,    4,  1,  43,  26,    6,  2,  19,  24,    6,  2,  15,  28,
40
    4,  0,  81,  20,    1,  4,  50,  30,    4,  4,  22,  28,    3,  8,  12,  24,
41
    2,  2,  92,  24,    6,  2,  36,  22,    4,  6,  20,  26,    7,  4,  14,  28,
42
    4,  0,  107, 26,    8,  1,  37,  22,    8,  4,  20,  24,    12, 4,  11,  22,
43
    3,  1,  115, 30,    4,  5,  40,  24,    11, 5,  16,  20,    11, 5,  12,  24,
44
    5,  1,  87,  22,    5,  5,  41,  24,    5,  7,  24,  30,    11, 7,  12,  24,
45
    5,  1,  98,  24,    7,  3,  45,  28,    15, 2,  19,  24,    3,  13, 15,  30,
46
    1,  5,  107, 28,    10, 1,  46,  28,    1,  15, 22,  28,    2,  17, 14,  28,
47
    5,  1,  120, 30,    9,  4,  43,  26,    17, 1,  22,  28,    2,  19, 14,  28,
48
    3,  4,  113, 28,    3,  11, 44,  26,    17, 4,  21,  26,    9,  16, 13,  26,
49
    3,  5,  107, 28,    3,  13, 41,  26,    15, 5,  24,  30,    15, 10, 15,  28,
50
    4,  4,  116, 28,    17, 0,  42,  26,    17, 6,  22,  28,    19, 6,  16,  30,
51
    2,  7,  111, 28,    17, 0,  46,  28,    7,  16, 24,  30,    34, 0,  13,  24,
52
    4,  5,  121, 30,    4,  14, 47,  28,    11, 14, 24,  30,    16, 14, 15,  30,
53
    6,  4,  117, 30,    6,  14, 45,  28,    11, 16, 24,  30,    30, 2,  16,  30,
54
    8,  4,  106, 26,    8,  13, 47,  28,    7,  22, 24,  30,    22, 13, 15,  30,
55
    10, 2,  114, 28,    19, 4,  46,  28,    28, 6,  22,  28,    33, 4,  16,  30,
56
    8,  4,  122, 30,    22, 3,  45,  28,    8,  26, 23,  30,    12, 28, 15,  30,
57
    3,  10, 117, 30,    3,  23, 45,  28,    4,  31, 24,  30,    11, 31, 15,  30,
58
    7,  7,  116, 30,    21, 7,  45,  28,    1,  37, 23,  30,    19, 26, 15,  30,
59
    5,  10, 115, 30,    19, 10, 47,  28,    15, 25, 24,  30,    23, 25, 15,  30,
60
    13, 3,  115, 30,    2,  29, 46,  28,    42, 1,  24,  30,    23, 28, 15,  30,
61
    17, 0,  115, 30,    10, 23, 46,  28,    10, 35, 24,  30,    19, 35, 15,  30,
62
    17, 1,  115, 30,    14, 21, 46,  28,    29, 19, 24,  30,    11, 46, 15,  30,
63
    13, 6,  115, 30,    14, 23, 46,  28,    44, 7,  24,  30,    59, 1,  16,  30,
64
    12, 7,  121, 30,    12, 26, 47,  28,    39, 14, 24,  30,    22, 41, 15,  30,
65
    6,  14, 121, 30,    6,  34, 47,  28,    46, 10, 24,  30,    2,  64, 15,  30,
66
    17, 4,  122, 30,    29, 14, 46,  28,    49, 10, 24,  30,    24, 46, 15,  30,
67
    4,  18, 122, 30,    13, 32, 46,  28,    48, 14, 24,  30,    42, 32, 15,  30,
68
    20, 4,  117, 30,    40, 7,  47,  28,    43, 22, 24,  30,    10, 67, 15,  30,
69
    19, 6,  118, 30,    18, 31, 47,  28,    34, 34, 24,  30,    20, 61, 15,  30
70
  ];
71
  // Map of human-readable ECC levels.
72
  var ECC_LEVELS = {
73
    L: 1,
74
    M: 2,
75
    Q: 3,
76
    H: 4
77
  };
78
  // Final format bits with mask (level << 3 | mask).
79
  var FINAL_FORMAT = [
80
    0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, /* L */
81
    0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, /* M */
82
    0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, /* Q */
83
    0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b  /* H */
84
  ];
85
  // Galois field exponent table.
86
  var GALOIS_EXPONENT = [
87
    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
88
    0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
89
    0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
90
    0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
91
    0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
92
    0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
93
    0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
94
    0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
95
    0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
96
    0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
97
    0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
98
    0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
99
    0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
100
    0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
101
    0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
102
    0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
103
  ];
104
  // Galois field log table.
105
  var GALOIS_LOG = [
106
    0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
107
    0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
108
    0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
109
    0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
110
    0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
111
    0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
112
    0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
113
    0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
114
    0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
115
    0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
116
    0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
117
    0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
118
    0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
119
    0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
120
    0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
121
    0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
122
  ];
123
  // *Badness* coefficients.
124
  var N1 = 3;
125
  var N2 = 3;
126
  var N3 = 40;
127
  var N4 = 10;
128
  // Version pattern.
129
  var VERSION_BLOCK = [ 
130
    0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532,
131
    0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5,
132
    0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69
133
  ];
134
  // Mode for node.js file system file writes.
135
  var WRITE_MODE = parseInt('0666', 8);
136
137
  // Private variables
138
  // -----------------
139
140
  // Run lengths for badness.
141
  var badBuffer = [];
142
  // Constructor for `canvas` elements in the node.js environment.
143
  var Canvas;
144
  // Data block.
145
  var dataBlock;
146
  // ECC data blocks and tables.
147
  var eccBlock, neccBlock1, neccBlock2;
148
  // ECC buffer.
149
  var eccBuffer = [];
150
  // ECC level (defaults to **L**).
151
  var eccLevel = 1;
152
  // Image buffer.
153
  var frameBuffer = [];
154
  // Fixed part of the image.
155
  var frameMask = [];
156
  // File system within the node.js environment.
157
  var fs;
158
  // Constructor for `img` elements in the node.js environment.
159
  var Image;
160
  // Indicates whether or not this script is running in node.js.
161
  var inNode = false;
162
  // Generator polynomial.
163
  var polynomial = [];
164
  // Save the previous value of the `qr` variable.
165
  var previousQr = root.qr;
166
  // Data input buffer.
167
  var stringBuffer = [];
168
  // Version for the data.
169
  var version;
170
  // Data width is based on `version`.
171
  var width;
172
173
  // Private functions
174
  // -----------------
175
176
  // Create a new canvas  using `document.createElement` unless script is running in node.js, in
177
  // which case the `canvas` module is used.
178
  function createCanvas() {
179
    return inNode ? new Canvas() : root.document.createElement('canvas');
180
  }
181
182
  // Create a new image using `document.createElement` unless script is running in node.js, in
183
  // which case the `canvas` module is used.
184
  function createImage() {
185
    return inNode ? new Image() : root.document.createElement('img');
186
  }
187
188
  // Force the canvas image to be downloaded in the browser.  
189
  // Optionally, a `callback` function can be specified which will be called upon completed. Since
190
  // this is not an asynchronous operation, this is merely convenient and helps simplify the
191
  // calling code.
192
  function download(cvs, data, callback) {
193
    var mime = data.mime || DEFAULT_MIME;
194
195
    root.location.href = cvs.toDataURL(mime).replace(mime, DOWNLOAD_MIME);
196
197
    if (typeof callback === 'function') callback();
198
  }
199
200
  // Normalize the `data` that is provided to the main API.
201
  function normalizeData(data) {
202
    if (typeof data === 'string') data = { value: data };
203
    return data || {};
204
  }
205
206
  // Override the `qr` API methods that require HTML5 canvas support to throw a relevant error.
207
  function overrideAPI(qr) {
208
    var methods = [ 'canvas', 'image', 'save', 'saveSync', 'toDataURL' ];
209
    var i;
210
211
    function overrideMethod(name) {
212
      qr[name] = function () {
213
        throw new Error(name + ' requires HTML5 canvas element support');
214
      };
215
    }
216
217
    for (i = 0; i < methods.length; i++) {
218
      overrideMethod(methods[i]);
219
    }
220
  }
221
222
  // Asynchronously write the data of the rendered canvas to a given file path.
223
  function writeFile(cvs, data, callback) {
224
    if (typeof data.path !== 'string') {
225
      return callback(new TypeError('Invalid path type: ' + typeof data.path));
226
    }
227
228
    var fd, buff;
229
230
    // Write the buffer to the open file stream once both prerequisites are met.
231
    function writeBuffer() {
232
      fs.write(fd, buff, 0, buff.length, 0, function (error) {
233
        fs.close(fd);
234
235
        callback(error);
236
      });
237
    }
238
239
    // Create a buffer of the canvas' data.
240
    cvs.toBuffer(function (error, _buff) {
241
      if (error) return callback(error);
242
243
      buff = _buff;
244
      if (fd) {
245
        writeBuffer();
246
      }
247
    });
248
249
    // Open a stream for the file to be written.
250
    fs.open(data.path, 'w', WRITE_MODE, function (error, _fd) {
251
      if (error) return callback(error);
252
253
      fd = _fd;
254
      if (buff) {
255
        writeBuffer();
256
      }
257
    });
258
  }
259
260
  // Write the data of the rendered canvas to a given file path.
261
  function writeFileSync(cvs, data) {
262
    if (typeof data.path !== 'string') {
263
      throw new TypeError('Invalid path type: ' + typeof data.path);
264
    }
265
266
    var buff = cvs.toBuffer();
267
    var fd = fs.openSync(data.path, 'w', WRITE_MODE);
268
269
    try {
270
      fs.writeSync(fd, buff, 0, buff.length, 0);
271
    } finally {
272
      fs.closeSync(fd);
273
    }
274
  }
275
276
  // Set bit to indicate cell in frame is immutable (symmetric around diagonal).
277
  function setMask(x, y) {
278
    var bit;
279
280
    if (x > y) {
281
      bit = x;
282
      x   = y;
283
      y   = bit;
284
    }
285
286
    bit   = y;
287
    bit  *= y;
288
    bit  += y;
289
    bit >>= 1;
290
    bit  += x;
291
292
    frameMask[bit] = 1;
293
  }
294
295
  // Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged
296
  // with mask later.
297
  function addAlignment(x, y) {
298
    var i;
299
300
    frameBuffer[x + width * y] = 1;
301
302
    for (i = -2; i < 2; i++) {
303
      frameBuffer[(x + i)     + width * (y - 2)]     = 1;
304
      frameBuffer[(x - 2)     + width * (y + i + 1)] = 1;
305
      frameBuffer[(x + 2)     + width * (y + i)]     = 1;
306
      frameBuffer[(x + i + 1) + width * (y + 2)]     = 1;
307
    }
308
309
    for (i = 0; i < 2; i++) {
310
      setMask(x - 1, y + i);
311
      setMask(x + 1, y - i);
312
      setMask(x - i, y - 1);
313
      setMask(x + i, y + 1);
314
    }
315
  }
316
317
  // Exponentiation mod N.
318
  function modN(x) {
319
    while (x >= 255) {
320
      x -= 255;
321
      x  = (x >> 8) + (x & 255);
322
    }
323
324
    return x;
325
  }
326
327
  // Calculate and append `ecc` data to the `data` block. If block is in the string buffer the
328
  // indices to buffers are used.
329
  function appendData(data, dataLength, ecc, eccLength) {
330
    var bit, i, j;
331
332
    for (i = 0; i < eccLength; i++) {
333
      stringBuffer[ecc + i] = 0;
334
    }
335
336
    for (i = 0; i < dataLength; i++) {
337
      bit = GALOIS_LOG[stringBuffer[data + i] ^ stringBuffer[ecc]];
338
339
      if (bit !== 255) {
340
        for (j = 1; j < eccLength; j++) {
341
          stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^
342
              GALOIS_EXPONENT[modN(bit + polynomial[eccLength - j])];
343
        }
344
      } else {
345
        for (j = ecc; j < ecc + eccLength; j++) {
346
          stringBuffer[j] = stringBuffer[j + 1];
347
        }
348
      }
349
350
      stringBuffer[ecc + eccLength - 1] = bit === 255 ? 0 :
351
          GALOIS_EXPONENT[modN(bit + polynomial[0])];
352
    }
353
  }
354
355
  // Check mask since symmetricals use half.
356
  function isMasked(x, y) {
357
    var bit;
358
359
    if (x > y) {
360
      bit = x;
361
      x   = y;
362
      y   = bit;
363
    }
364
365
    bit   = y;
366
    bit  += y * y;
367
    bit >>= 1;
368
    bit  += x;
369
370
    return frameMask[bit] === 1;
371
  }
372
373
  // Apply the selected mask out of the 8 options.
374
  function applyMask(mask) {
375
    var x, y, r3x, r3y;
376
377
    switch (mask) {
378
      case 0:
379
        for (y = 0; y < width; y++) {
380
          for (x = 0; x < width; x++) {
381
            if (!((x + y) & 1) && !isMasked(x, y)) {
382
              frameBuffer[x + y * width] ^= 1;
383
            }
384
          }
385
        }
386
387
        break;
388
      case 1:
389
        for (y = 0; y < width; y++) {
390
          for (x = 0; x < width; x++) {
391
            if (!(y & 1) && !isMasked(x, y)) {
392
              frameBuffer[x + y * width] ^= 1;
393
            }
394
          }
395
        }
396
397
        break;
398
      case 2:
399
        for (y = 0; y < width; y++) {
400
          for (r3x = 0, x = 0; x < width; x++, r3x++) {
401
            if (r3x === 3) r3x = 0;
402
403
            if (!r3x && !isMasked(x, y)) {
404
              frameBuffer[x + y * width] ^= 1;
405
            }
406
          }
407
        }
408
409
        break;
410
      case 3:
411
        for (r3y = 0, y = 0; y < width; y++, r3y++) {
412
          if (r3y === 3) r3y = 0;
413
414
          for (r3x = r3y, x = 0; x < width; x++, r3x++) {
415
            if (r3x === 3) r3x = 0;
416
417
            if (!r3x && !isMasked(x, y)) {
418
              frameBuffer[x + y * width] ^= 1;
419
            }
420
          }
421
        }
422
423
        break;
424
      case 4:
425
        for (y = 0; y < width; y++) {
426
          for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) {
427
            if (r3x === 3) {
428
              r3x = 0;
429
              r3y = !r3y;
430
            }
431
432
            if (!r3y && !isMasked(x, y)) {
433
              frameBuffer[x + y * width] ^= 1;
434
            }
435
          }
436
        }
437
438
        break;
439
      case 5:
440
        for (r3y = 0, y = 0; y < width; y++, r3y++) {
441
          if (r3y === 3) r3y = 0;
442
443
          for (r3x = 0, x = 0; x < width; x++, r3x++) {
444
            if (r3x === 3) r3x = 0;
445
446
            if (!((x & y & 1) + !(!r3x | !r3y)) && !isMasked(x, y)) {
447
              frameBuffer[x + y * width] ^= 1;
448
            }
449
          }
450
        }
451
452
        break;
453
      case 6:
454
        for (r3y = 0, y = 0; y < width; y++, r3y++) {
455
          if (r3y === 3) r3y = 0;
456
457
          for (r3x = 0, x = 0; x < width; x++, r3x++) {
458
            if (r3x === 3) r3x = 0;
459
460
            if (!(((x & y & 1) + (r3x && (r3x === r3y))) & 1) && !isMasked(x, y)) {
461
              frameBuffer[x + y * width] ^= 1;
462
            }
463
          }
464
        }
465
466
        break;
467
      case 7:
468
        for (r3y = 0, y = 0; y < width; y++, r3y++) {
469
          if (r3y === 3) r3y = 0;
470
471
          for (r3x = 0, x = 0; x < width; x++, r3x++) {
472
            if (r3x === 3) r3x = 0;
473
474
            if (!(((r3x && (r3x === r3y)) + ((x + y) & 1)) & 1) && !isMasked(x, y)) {
475
              frameBuffer[x + y * width] ^= 1;
476
            }
477
          }
478
        }
479
480
        break;
481
    }
482
  }
483
484
  // Using the table for the length of each run, calculate the amount of bad image. Long runs or
485
  // those that look like finders are called twice; once for X and Y.
486
  function getBadRuns(length) {
487
    var badRuns = 0;
488
    var i;
489
490
    for (i = 0; i <= length; i++) {
491
      if (badBuffer[i] >= 5) {
492
        badRuns += N1 + badBuffer[i] - 5;
493
      }
494
    }
495
496
    // FBFFFBF as in finder.
497
    for (i = 3; i < length - 1; i += 2) {
498
      if (badBuffer[i - 2] === badBuffer[i + 2] &&
499
          badBuffer[i + 2] === badBuffer[i - 1] &&
500
          badBuffer[i - 1] === badBuffer[i + 1] &&
501
          badBuffer[i - 1] * 3 === badBuffer[i] &&
502
          // Background around the foreground pattern? Not part of the specs.
503
          (badBuffer[i - 3] === 0 || i + 3 > length ||
504
           badBuffer[i - 3] * 3 >= badBuffer[i] * 4 ||
505
           badBuffer[i + 3] * 3 >= badBuffer[i] * 4)) {
506
        badRuns += N3;
507
      }
508
    }
509
510
    return badRuns;
511
  }
512
513
  // Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders).
514
  function checkBadness() {
515
    var b, b1, bad, big, bw, count, h, x, y;
516
    bad = bw = count = 0;
517
518
    // Blocks of same colour.
519
    for (y = 0; y < width - 1; y++) {
520
      for (x = 0; x < width - 1; x++) {
521
            // All foreground colour.
522
        if ((frameBuffer[x + width * y] &&
523
             frameBuffer[(x + 1) + width * y] &&
524
             frameBuffer[x + width * (y + 1)] &&
525
             frameBuffer[(x + 1) + width * (y + 1)]) ||
526
            // All background colour.
527
            !(frameBuffer[x + width * y] ||
528
              frameBuffer[(x + 1) + width * y] ||
529
              frameBuffer[x + width * (y + 1)] ||
530
              frameBuffer[(x + 1) + width * (y + 1)])) {
531
          bad += N2;
532
        }
533
      }
534
    }
535
536
    // X runs.
537
    for (y = 0; y < width; y++) {
538
      badBuffer[0] = 0;
539
540
      for (h = b = x = 0; x < width; x++) {
541
        if ((b1 = frameBuffer[x + width * y]) === b) {
542
          badBuffer[h]++;
543
        } else {
544
          badBuffer[++h] = 1;
545
        }
546
547
        b   = b1;
548
        bw += b ? 1 : -1;
549
      }
550
551
      bad += getBadRuns(h);
552
    }
553
554
    if (bw < 0) bw = -bw;
555
556
    big   = bw;
557
    big  += big << 2;
558
    big <<= 1;
559
560
    while (big > width * width) {
561
      big -= width * width;
562
      count++;
563
    }
564
565
    bad += count * N4;
566
567
    // Y runs.
568
    for (x = 0; x < width; x++) {
569
      badBuffer[0] = 0;
570
571
      for (h = b = y = 0; y < width; y++) {
572
        if ((b1 = frameBuffer[x + width * y]) === b) {
573
          badBuffer[h]++;
574
        } else {
575
          badBuffer[++h] = 1;
576
        }
577
578
        b = b1;
579
      }
580
581
      bad += getBadRuns(h);
582
    }
583
584
    return bad;
585
  }
586
587
  // Generate the encoded QR image for the string provided.
588
  function generateFrame(str) {
589
    var i, j, k, m, t, v, x, y;
590
591
    // Find the smallest version that fits the string.
592
    t = str.length;
593
594
    version = 0;
595
596
    do {
597
      version++;
598
599
      k = (eccLevel - 1) * 4 + (version - 1) * 16;
600
601
      neccBlock1 = ECC_BLOCKS[k++];
602
      neccBlock2 = ECC_BLOCKS[k++];
603
      dataBlock  = ECC_BLOCKS[k++];
604
      eccBlock   = ECC_BLOCKS[k];
605
606
      k = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 - 3 + (version <= 9);
607
608
      if (t <= k) break;
609
    } while (version < 40);
610
611
    // FIXME: Ensure that it fits insted of being truncated.
612
    width = 17 + 4 * version;
613
614
    // Allocate, clear and setup data structures.
615
    v = dataBlock + (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2;
616
617
    for (t = 0; t < v; t++) {
618
      eccBuffer[t] = 0;
619
    }
620
621
    stringBuffer = str.slice(0);
622
623
    for (t = 0; t < width * width; t++) {
624
      frameBuffer[t] = 0;
625
    }
626
627
    for (t = 0; t < (width * (width + 1) + 1) / 2; t++) {
628
      frameMask[t] = 0;
629
    }
630
631
    // Insert finders: Foreground colour to frame and background to mask.
632
    for (t = 0; t < 3; t++) {
633
      k = y = 0;
634
635
      if (t === 1) k = (width - 7);
636
      if (t === 2) y = (width - 7);
637
638
      frameBuffer[(y + 3) + width * (k + 3)] = 1;
639
640
      for (x = 0; x < 6; x++) {
641
        frameBuffer[(y + x) + width * k] = 1;
642
        frameBuffer[y + width * (k + x + 1)] = 1;
643
        frameBuffer[(y + 6) + width * (k + x)] = 1;
644
        frameBuffer[(y + x + 1) + width * (k + 6)] = 1;
645
      }
646
647
      for (x = 1; x < 5; x++) {
648
        setMask(y + x, k + 1);
649
        setMask(y + 1, k + x + 1);
650
        setMask(y + 5, k + x);
651
        setMask(y + x + 1, k + 5);
652
      }
653
654
      for (x = 2; x < 4; x++) {
655
        frameBuffer[(y + x) + width * (k + 2)] = 1;
656
        frameBuffer[(y + 2) + width * (k + x + 1)] = 1;
657
        frameBuffer[(y + 4) + width * (k + x)] = 1;
658
        frameBuffer[(y + x + 1) + width * (k + 4)] = 1;
659
      }
660
    }
661
662
    // Alignment blocks.
663
    if (version > 1) {
664
      t = ALIGNMENT_DELTA[version];
665
      y = width - 7;
666
667
      for (;;) {
668
        x = width - 7;
669
670
        while (x > t - 3) {
671
          addAlignment(x, y);
672
673
          if (x < t) break;
674
675
          x -= t;
676
        }
677
678
        if (y <= t + 9) break;
679
680
        y -= t;
681
682
        addAlignment(6, y);
683
        addAlignment(y, 6);
684
      }
685
    }
686
687
    // Single foreground cell.
688
    frameBuffer[8 + width * (width - 8)] = 1;
689
690
    // Timing gap (mask only).
691
    for (y = 0; y < 7; y++) {
692
      setMask(7, y);
693
      setMask(width - 8, y);
694
      setMask(7, y + width - 7);
695
    }
696
697
    for (x = 0; x < 8; x++) {
698
      setMask(x, 7);
699
      setMask(x + width - 8, 7);
700
      setMask(x, width - 8);
701
    }
702
703
    // Reserve mask, format area.
704
    for (x = 0; x < 9; x++) {
705
      setMask(x, 8);
706
    }
707
708
    for (x = 0; x < 8; x++) {
709
      setMask(x + width - 8, 8);
710
      setMask(8, x);
711
    }
712
713
    for (y = 0; y < 7; y++) {
714
      setMask(8, y + width - 7);
715
    }
716
717
    // Timing row/column.
718
    for (x = 0; x < width - 14; x++) {
719
      if (x & 1) {
720
        setMask(8 + x, 6);
721
        setMask(6, 8 + x);
722
      } else {
723
        frameBuffer[(8 + x) + width * 6] = 1;
724
        frameBuffer[6 + width * (8 + x)] = 1;
725
      }
726
    }
727
728
    // Version block.
729
    if (version > 6) {
730
      t = VERSION_BLOCK[version - 7];
731
      k = 17;
732
733
      for (x = 0; x < 6; x++) {
734
        for (y = 0; y < 3; y++, k--) {
735
          if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
736
            frameBuffer[(5 - x) + width * (2 - y + width - 11)] = 1;
737
            frameBuffer[(2 - y + width - 11) + width * (5 - x)] = 1;
738
          } else {
739
            setMask(5 - x, 2 - y + width - 11);
740
            setMask(2 - y + width - 11, 5 - x);
741
          }
742
        }
743
      }
744
    }
745
746
    // Sync mask bits. Only set above for background cells, so now add the foreground.
747
    for (y = 0; y < width; y++) {
748
      for (x = 0; x <= y; x++) {
749
        if (frameBuffer[x + width * y]) {
750
          setMask(x, y);
751
        }
752
      }
753
    }
754
755
    // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji
756
    // not supported).
757
    v = stringBuffer.length;
758
759
    // String to array.
760
    for (i = 0; i < v; i++) {
761
      eccBuffer[i] = stringBuffer.charCodeAt(i);
762
    }
763
764
    stringBuffer = eccBuffer.slice(0);
765
766
    // Calculate max string length.
767
    x = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2;
768
769
    if (v >= x - 2) {
770
      v = x - 2;
771
772
      if (version > 9) v--;
773
    }
774
775
    // Shift and re-pack to insert length prefix.
776
    i = v;
777
778
    if (version > 9) {
779
      stringBuffer[i + 2] = 0;
780
      stringBuffer[i + 3] = 0;
781
782
      while (i--) {
783
        t = stringBuffer[i];
784
785
        stringBuffer[i + 3] |= 255 & (t << 4);
786
        stringBuffer[i + 2] = t >> 4;
787
      }
788
789
      stringBuffer[2] |= 255 & (v << 4);
790
      stringBuffer[1] = v >> 4;
791
      stringBuffer[0] = 0x40 | (v >> 12);
792
    } else {
793
      stringBuffer[i + 1] = 0;
794
      stringBuffer[i + 2] = 0;
795
796
      while (i--) {
797
        t = stringBuffer[i];
798
799
        stringBuffer[i + 2] |= 255 & (t << 4);
800
        stringBuffer[i + 1] = t >> 4;
801
      }
802
803
      stringBuffer[1] |= 255 & (v << 4);
804
      stringBuffer[0] = 0x40 | (v >> 4);
805
    }
806
807
    // Fill to end with pad pattern.
808
    i = v + 3 - (version < 10);
809
810
    while (i < x) {
811
      stringBuffer[i++] = 0xec;
812
      stringBuffer[i++] = 0x11;
813
    }
814
815
    // Calculate generator polynomial.
816
    polynomial[0] = 1;
817
818
    for (i = 0; i < eccBlock; i++) {
819
      polynomial[i + 1] = 1;
820
821
      for (j = i; j > 0; j--) {
822
        polynomial[j] = polynomial[j] ? polynomial[j - 1] ^
823
            GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[j]] + i)] : polynomial[j - 1];
824
      }
825
826
      polynomial[0] = GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[0]] + i)];
827
    }
828
829
    // Use logs for generator polynomial to save calculation step.
830
    for (i = 0; i <= eccBlock; i++) {
831
      polynomial[i] = GALOIS_LOG[polynomial[i]];
832
    }
833
834
    // Append ECC to data buffer.
835
    k = x;
836
    y = 0;
837
838
    for (i = 0; i < neccBlock1; i++) {
839
      appendData(y, dataBlock, k, eccBlock);
840
841
      y += dataBlock;
842
      k += eccBlock;
843
    }
844
845
    for (i = 0; i < neccBlock2; i++) {
846
      appendData(y, dataBlock + 1, k, eccBlock);
847
848
      y += dataBlock + 1;
849
      k += eccBlock;
850
    }
851
852
    // Interleave blocks.
853
    y = 0;
854
855
    for (i = 0; i < dataBlock; i++) {
856
      for (j = 0; j < neccBlock1; j++) {
857
        eccBuffer[y++] = stringBuffer[i + j * dataBlock];
858
      }
859
860
      for (j = 0; j < neccBlock2; j++) {
861
        eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))];
862
      }
863
    }
864
865
    for (j = 0; j < neccBlock2; j++) {
866
      eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))];
867
    }
868
869
    for (i = 0; i < eccBlock; i++) {
870
      for (j = 0; j < neccBlock1 + neccBlock2; j++) {
871
        eccBuffer[y++] = stringBuffer[x + i + j * eccBlock];
872
      }
873
    }
874
875
    stringBuffer = eccBuffer;
876
877
    // Pack bits into frame avoiding masked area.
878
    x = y = width - 1;
879
    k = v = 1;
880
881
    // inteleaved data and ECC codes.
882
    m = (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2;
883
884
    for (i = 0; i < m; i++) {
885
      t = stringBuffer[i];
886
887
      for (j = 0; j < 8; j++, t <<= 1) {
888
        if (0x80 & t) {
889
          frameBuffer[x + width * y] = 1;
890
        }
891
892
        // Find next fill position.
893
        do {
894
          if (v) {
895
            x--;
896
          } else {
897
            x++;
898
899
            if (k) {
900
              if (y !== 0) {
901
                y--;
902
              } else {
903
                x -= 2;
904
                k  = !k;
905
906
                if (x === 6) {
907
                  x--;
908
                  y = 9;
909
                }
910
              }
911
            } else {
912
              if (y !== width - 1) {
913
                y++;
914
              } else {
915
                x -= 2;
916
                k  = !k;
917
918
                if (x === 6) {
919
                  x--;
920
                  y -= 8;
921
                }
922
              }
923
            }
924
          }
925
926
          v = !v;
927
        } while (isMasked(x, y));
928
      }
929
    }
930
931
    // Save pre-mask copy of frame.
932
    stringBuffer = frameBuffer.slice(0);
933
934
    t = 0;
935
    y = 30000;
936
937
    // Using `for` instead of `while` since in original Arduino code if an early mask was *good
938
    // enough* it wouldn't try for a better one since they get more complex and take longer.
939
    for (k = 0; k < 8; k++) {
940
      // Returns foreground-background imbalance.
941
      applyMask(k);
942
943
      x = checkBadness();
944
945
      // Is current mask better than previous best?
946
      if (x < y) {
947
        y = x;
948
        t = k;
949
      }
950
951
      // Don't increment `i` to a void redoing mask.
952
      if (t === 7) break;
953
954
      // Reset for next pass.
955
      frameBuffer = stringBuffer.slice(0);
956
    }
957
958
    // Redo best mask as none were *good enough* (i.e. last wasn't `t`).
959
    if (t !== k) {
960
      applyMask(t);
961
    }
962
963
    // Add in final mask/ECC level bytes.
964
    y = FINAL_FORMAT[t + ((eccLevel - 1) << 3)];
965
966
    // Low byte.
967
    for (k = 0; k < 8; k++, y >>= 1) {
968
      if (y & 1) {
969
        frameBuffer[(width - 1 - k) + width * 8] = 1;
970
971
        if (k < 6) {
972
          frameBuffer[8 + width * k] = 1;
973
        } else {
974
          frameBuffer[8 + width * (k + 1)] = 1;
975
        }
976
      }
977
    }
978
979
    // High byte.
980
    for (k = 0; k < 7; k++, y >>= 1) {
981
      if (y & 1) {
982
        frameBuffer[8 + width * (width - 7 + k)] = 1;
983
984
        if (k) {
985
          frameBuffer[(6 - k) + width * 8] = 1;
986
        } else {
987
          frameBuffer[7 + width * 8] = 1;
988
        }
989
      }
990
    }
991
992
    // Finally, return the image data.
993
    return frameBuffer;
994
  }
995
996
  // qr.js setup
997
  // -----------
998
999
  // Build the publicly exposed API.
1000
  var qr = {
1001
1002
    // Constants
1003
    // ---------
1004
1005
    // Current version of `qr`.
1006
    VERSION: '1.1.4',
1007
1008
    // QR functions
1009
    // ------------
1010
1011
    // Generate the QR code using the data provided and render it on to a `<canvas>` element.  
1012
    // If no `<canvas>` element is specified in the argument provided a new one will be created and
1013
    // used.  
1014
    // ECC (error correction capacity) determines how many intential errors are contained in the QR
1015
    // code.
1016
    canvas: function(data) {
1017
      data = normalizeData(data);
1018
1019
      // Module size of the generated QR code (i.e. 1-10).
1020
      var size = data.size >= 1 && data.size <= 10 ? data.size : 4;
1021
      // Actual size of the QR code symbol and is scaled to 25 pixels (e.g. 1 = 25px, 3 = 75px).
1022
      size *= 25;
1023
1024
      // `<canvas>` element used to render the QR code.
1025
      var cvs = data.canvas || createCanvas();
1026
      // Retreive the 2D context of the canvas.
1027
      var c2d = cvs.getContext('2d');
1028
      // Ensure the canvas has the correct dimensions.
1029
      c2d.canvas.width  = size;
1030
      c2d.canvas.height = size;
1031
      // Fill the canvas with the correct background colour.
1032
      c2d.fillStyle = data.background || '#fff';
1033
      c2d.fillRect(0, 0, size, size);
1034
1035
      // Determine the ECC level to be applied.
1036
      eccLevel = ECC_LEVELS[(data.level && data.level.toUpperCase()) || 'L'];
1037
1038
      // Generate the image frame for the given `value`.
1039
      var frame = generateFrame(data.value || '');
1040
1041
      c2d.lineWidth = 1;
1042
1043
      // Determine the *pixel* size.
1044
      var px = size;
1045
      px /= width;
1046
      px  = Math.floor(px);
1047
1048
      var offset = Math.floor((size - (px * width)) / 2);
1049
1050
      // Draw the QR code.
1051
      c2d.clearRect(0, 0, size, size);
1052
      c2d.fillStyle = data.background || '#fff';
1053
      c2d.fillRect(0, 0, size, size);
1054
      c2d.fillStyle = data.foreground || '#000';
1055
1056
      var i, j;
1057
1058
      for (i = 0; i < width; i++) {
1059
        for (j = 0; j < width; j++) {
1060
          if (frame[j * width + i]) {
1061
            c2d.fillRect(px * i + offset, px * j + offset, px, px);
1062
          }
1063
        }
1064
      }
1065
1066
      return cvs;
1067
    },
1068
1069
    // Generate the QR code using the data provided and render it on to a `<img>` element.  
1070
    // If no `<img>` element is specified in the argument provided a new one will be created and
1071
    // used.  
1072
    // ECC (error correction capacity) determines how many intential errors are contained in the QR
1073
    // code.
1074
    image: function(data) {
1075
      data = normalizeData(data);
1076
1077
      // `<canvas>` element only which the QR code is rendered.
1078
      var cvs = this.canvas(data);
1079
      // `<img>` element used to display the QR code.
1080
      var img = data.image || createImage();
1081
1082
      // Apply the QR code to `img`.
1083
      img.src    = cvs.toDataURL(data.mime || DEFAULT_MIME);
1084
      img.height = cvs.height;
1085
      img.width  = cvs.width;
1086
1087
      return img;
1088
    },
1089
1090
    // Generate the QR code using the data provided and render it on to a `<canvas>` element and
1091
    // save it as an image file.  
1092
    // If no `<canvas>` element is specified in the argument provided a new one will be created and
1093
    // used.  
1094
    // ECC (error correction capacity) determines how many intential errors are contained in the QR
1095
    // code.  
1096
    // If called in a browser the `path` property/argument is ignored and will simply prompt the
1097
    // user to choose a location and file name. However, if called within node.js the file will be
1098
    // saved to specified path.  
1099
    // A `callback` function must be provided which will be called once the saving process has
1100
    // started. If an error occurs it will be passed as the first argument to this function,
1101
    // otherwise this argument will be `null`.
1102
    save: function(data, path, callback) {
1103
      data = normalizeData(data);
1104
1105
      switch (typeof path) {
1106
        case 'function':
1107
          callback = path;
1108
          path = null;
1109
          break;
1110
        case 'string':
1111
          data.path = path;
1112
          break;
1113
      }
1114
1115
      // Callback function is required.
1116
      if (typeof callback !== 'function') {
1117
        throw new TypeError('Invalid callback type: ' + typeof callback);
1118
      }
1119
1120
      var completed = false;
1121
      // `<canvas>` element only which the QR code is rendered.
1122
      var cvs = this.canvas(data);
1123
1124
      // Simple function to try and ensure that the `callback` function is only called once.
1125
      function done(error) {
1126
        if (!completed) {
1127
          completed = true;
1128
1129
          callback(error);
1130
        }
1131
      }
1132
1133
      if (inNode) {
1134
        writeFile(cvs, data, done);
1135
      } else {
1136
        download(cvs, data, done);
1137
      }
1138
    },
1139
1140
    // Generate the QR code using the data provided and render it on to a `<canvas>` element and
1141
    // save it as an image file.  
1142
    // If no `<canvas>` element is specified in the argument provided a new one will be created and
1143
    // used.  
1144
    // ECC (error correction capacity) determines how many intential errors are contained in the QR
1145
    // code.  
1146
    // If called in a browser the `path` property/argument is ignored and will simply prompt the
1147
    // user to choose a location and file name. However, if called within node.js the file will be
1148
    // saved to specified path.
1149
    saveSync: function(data, path) {
1150
      data = normalizeData(data);
1151
1152
      if (typeof path === 'string') data.path = path;
1153
1154
      // `<canvas>` element only which the QR code is rendered.
1155
      var cvs = this.canvas(data);
1156
1157
      if (inNode) {
1158
        writeFileSync(cvs, data);
1159
      } else {
1160
        download(cvs, data);
1161
      }
1162
    },
1163
1164
    // Generate the QR code using the data provided and render it on to a `<canvas>` element before
1165
    // returning its data URI.  
1166
    // If no `<canvas>` element is specified in the argument provided a new one will be created and
1167
    // used.  
1168
    // ECC (error correction capacity) determines how many intential errors are contained in the QR
1169
    // code.
1170
    toDataURL: function(data) {
1171
      data = normalizeData(data);
1172
1173
      return this.canvas(data).toDataURL(data.mime || DEFAULT_MIME);
1174
    },
1175
1176
    // Utility functions
1177
    // -----------------
1178
1179
    // Run qr.js in *noConflict* mode, returning the `qr` variable to its previous owner.  
1180
    // Returns a reference to `qr`.
1181
    noConflict: function() {
1182
      root.qr = previousQr;
1183
      return this;
1184
    }
1185
1186
  };
1187
1188
  // Support
1189
  // -------
1190
1191
  // Export `qr` for node.js and CommonJS.
1192
  if (typeof exports !== 'undefined') {
1193
    inNode = true;
1194
1195
    if (typeof module !== 'undefined' && module.exports) {
1196
      exports = module.exports = qr;
1197
    }
1198
    exports.qr = qr;
1199
1200
    // Import required node.js modules.
1201
    Canvas = require('canvas');
1202
    Image = Canvas.Image;
1203
    fs = require('fs');
1204
  } else if (typeof define === 'function' && define.amd) {
1205
    define(function () {
1206
      return qr;
1207
    });
1208
  } else {
1209
    // In non-HTML5 browser so strip base functionality.
1210
    if (!root.HTMLCanvasElement) {
1211
      overrideAPI(qr);
1212
    }
1213
1214
    root.qr = qr;
1215
  }
1216
1217
})(this);
1218